<template>
	<el-dialog title="问题库导入" :visible.sync="showDialog" :before-close="cancel" width="10rem">
		<div>
			<span>填写模版文件，表头不可修改及删除</span>
			<el-link type="primary" class="detail-link" style="padding: 0 5px" :underline="false" :href="excelUrl" target="_blank">
				<el-button class="download-button"><i class="el-icon-download el-icon--left"></i>下载模版</el-button>
			</el-link>
		</div>
		<br />
		<el-upload
			v-loading="loading"
			element-loading-text="数据校验中..."
			element-loading-spinner="el-icon-loading"
			element-loading-background="rgba(255, 255, 255, 0.8)"
			accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
			ref="uploadRef"
			:on-remove="onRemoveUploadFile"
			:on-change="onFileChange"
			@drop.native="e => dragToUpload(e)"
			:file-list="uploadFileList"
			class="upload-demo"
			style="align-items: center; display: flex; flex-direction: column"
			drag
			:auto-upload="false"
			:on-progress="onUploadProgress"
			:action="uploadFileConfig.url"
			:headers="uploadFileConfig.headers"
			:show-file-list="false"
			:on-exceed="onAnotherFile"
			limit="1"
		>
			<div class="el-upload__tip" slot="tip"></div>
			<div class="el-upload__trigger before-upload-box" v-if="uploadFileList.length === 0" slot="trigger">
				<i class="el-icon-excel"></i>
				<div class="el-upload__text upload-text">点击或拖拽上传，仅支持Excel文件，不超过1000行</div>
			</div>
			<div class="upload-box" v-else slot="trigger">
				<div class="upload-items">
					<i class="el-icon-excel excel-img"></i>
					<div class="el-upload__text excel-name">{{ this.uploadFileList[0].name }}</div>
					<i class="el-icon-close excel-remove" @click="removeUploadFile($event)"></i>
				</div>
			</div>
		</el-upload>
		<span v-show="uploadFileList.length === 0 && clickedSubmit" style="color: red">请选择导入文件</span>
		<span v-show="uploadFileList.length > 0 && clickedSubmit" style="color: red">正在导入... 请不要刷新或离开，否则将会导入失败</span>
		<br />
		<div class="btns">
			<el-button @click="cancel">取消</el-button>
			<el-button type="primary" @click="submit($event)">确认</el-button>
		</div>
	</el-dialog>
</template>

<script>
import { mapState } from 'vuex';
import { fixUploadPercent, forceBtnBlur } from '@/utils/MyVueUtil';
import XLSX from 'xlsx';
import { getUploadFileConfig, getKnowledgeBaseCategoryAll, importKnowledgeBase } from '@/api/api';
// import { getValidateQuestionNameResult, getValidateQuestionAnswerResult } from '@/utils/formValidate';
// import { groupMock } from './mock';

export default {
	components: {},
	props: {
		show: {
			type: Boolean,
			default: false
		}
	},
	data() {
		return {
			clickedSubmit: false,
			excelUrl: importKbTemplateUrl,
			uploadFileList: [],
			uploadFileConfig: getUploadFileConfig(),
			loading: false,
			showDialog: true,
			existedGroups: [],
			questionList: []
		};
	},
	watch: {
		show(newVal) {
			this.showDialog = newVal;
			if (newVal) {
				this.refreshAllGroups();
			}
		}
	},
	computed: {
		...mapState({
			loginInfo: state => state.login.userInfo
		})
	},
	mounted() {
		this.refreshAllGroups();
	},
	methods: {
		reset() {
			this.uploadFileList = [];
			this.$refs.uploadRef.clearFiles();
			this.clickedSubmit = false;
			this.loading = false;
		},
		removeUploadFile(e) {
			this.reset();
			e.stopPropagation();
		},
		refreshAllGroups() {
			getKnowledgeBaseCategoryAll()
				.then(res => {
					this.existedGroups = res.data.data || [];
					console.log('this.existedGroups', this.existedGroups);
				})
				.catch(error => {
					this.$message.error('获取问题分类列表失败！');
					console.log('getKnowledgeBaseCategoryAll failed:', error);
				});
		},
		submit(event) {
			forceBtnBlur(event);
			if (this.uploadFileList.length > 0) {
				this.clickedSubmit = true;
				importKnowledgeBase({data: this.questionList})
					.then(res => {
						this.$emit('imported');
						this.$message.success('导入成功！');
					})
					.catch(error => {
						console.log('importKnowledgeBase error:', error);
						const { nameEmptyError, nameLengthError, answerEmptyError, typeofAnswerError, answerLengthError, notFoundCategoryIdError, notAllowToCreateKnowledge, existNameInDbError } = error.data;
						let checkResult = '';
						if (nameEmptyError.length > 0) {
							checkResult += `第 ${nameEmptyError.join(',')} 行, 问题标题为空，请重新编辑后再导入！<br />`;
						}
						if (nameLengthError.length > 0) {
							checkResult += `第 ${nameLengthError.join(',')} 行, 格式错误，问题标题最多支持250个字符<br />`;
						}
						if (answerEmptyError.length > 0) {
							checkResult += `第 ${answerEmptyError.join(',')} 行, 答案内容为空，请重新编辑后再导入！<br />`;
						}
						if (typeofAnswerError.length > 0) {
							checkResult += `第 ${typeofAnswerError.join(',')} 行, 格式错误，答案内容只能为纯文本<br />`;
						}
						if (answerLengthError.length > 0) {
							checkResult += `第 ${answerLengthError.join(',')} 行, 格式错误，答案内容最多支持2000个字符”<br />`;
						}
						if (notFoundCategoryIdError.length > 0) {
							checkResult += `第 ${notFoundCategoryIdError.join(',')} 行, 分类不存在，请重新编辑后再导入<br />`;
						}
						if (notAllowToCreateKnowledge.length > 0) {
							checkResult += `第 ${notAllowToCreateKnowledge.join(',')} 行, 存在子分类，请重新编辑后再导入<br />`;
						}
						if (existNameInDbError.length > 0) {
							checkResult += `第 ${existNameInDbError.join(',')} 行, 问题标题系统中已存在！<br />`;
						}
						if (checkResult) {
							this.$alert(`<div style="overflow-y:scroll;overflow-x:hidden;max-height:300px">${checkResult}</div>`, '导入失败', {
								confirmButtonText: '确定',
								dangerouslyUseHTMLString: true
							});
						} else {
							this.$message.warning('导入失败');
						}
						this.refreshAllGroups();

					})
					.finally(() => {
						this.reset();
						this.clickedSubmit = false;
					});
			} else {
				this.clickedSubmit = true;
				// this.$message.warning('请先上传 Excel 文件！')
			}
		},
		cancel() {
			this.reset();
			this.$emit('close');
		},
		onRemoveUploadFile(file, fileList) {
			this.uploadFileList = [];
		},
		dragToUpload(e) {
			console.log('drop event:', e.dataTransfer.files[0]);
			this.onFileChange({ raw: e.dataTransfer.files[0], size: e.dataTransfer.files[0].size, name: e.dataTransfer.files[0].name }, null);
		},
		onAnotherFile(files, fileList) {
			console.log('1:', this.uploadFileList);
			console.log('2:', files);
			if (this.uploadFileList[0].name === files[0].name && this.uploadFileList[0].lastModified === files[0].lastModified && this.uploadFileList[0].size === files[0].size) {
				// 是之前上传的文件再做处理
			} else {
				this.onFileChange({ raw: files[0], size: files[0].size, name: files[0].name }, null);
			}
		},
		onFileChange(file, fileList) {
			this.loading = true;
			this.clickedSubmit = false;
			const isExcel = file.raw.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
			if (!isExcel) {
				this.$message.error('格式不正确，仅支持Excel文件导入');
				this.reset();
				return;
			}
			// 上传文件大小小于50M：提示文案：{color:#ff0000}请上传小于50M的文件！
			if (file.size > excelMaxSize) {
				const size = Math.floor(excelMaxSize / 1024 / 1024);
				this.$message.error(`请上传小于${size}M的文件！`);
				this.reset();
				return;
			}
			// 这里稍微延迟一下，让 loading 效果展示出来，否则在读取比较耗时的 Excel 文件时，loading 效果有几率展示不出来
			// 必填：问题标题	答案内容	非必填：一级问题分类	二级问题分类	三级问题分类
			setTimeout(() => {
				let fileReader = new FileReader();
				fileReader.readAsBinaryString(file.raw);
				fileReader.onload = e => {
					this.submitList = []; // 用于存放提交的数据
					// 读取 excel 表格中数据
					let data = e.target.result;
					let workbook = XLSX.read(data, { type: 'binary' });
					let sheetNames = workbook.SheetNames;
					// if (sheetNames.length !== 1) {
					// 	this.$message.error('Excel 中只允许有一张表');
					// 	this.reset();
					// 	return;
					// }

					let firstSheet = XLSX.utils.sheet_to_json(workbook.Sheets[sheetNames[0]], { blankrows: true, defval: '' });
					if (firstSheet.length === 0) {
						this.$message.error('Excel 中没有数据！');
						this.reset();
						return;
					}
					if (firstSheet.length > 1000) {
						console.log('excel groups sheet:', firstSheet);
						this.$message.error('Excel 中最大只允许 1000 条数据！');
						this.reset();
						return;
					}
					// 校验表格中各个字段后的结果汇总
					let checkResult = '';
					// 校验 excel 表格的表头是否符合格式 表头内容修改或删除时弹窗提示“第x,y,z行  请勿修改表格表头信息，请重新编辑后再导入”
					// excel 中表格表头，必须按照 excel 表头顺序存放
					let tempKeys = ['问题标题', '答案内容', '一级问题分类', '二级问题分类', '三级问题分类'];
					let keys = Object.keys(firstSheet[0]);
					for (let i = 0; i < tempKeys.length; i++) {
						if (tempKeys[i] !== keys[i]) {
							checkResult += `表单第 ${String.fromCharCode(i + 65)} 列，应该为 ${tempKeys[i]}<br />`;
						}
					}
					this.questionList = [];
					// excel 符合规范后再校验每列
					if (checkResult.length === 0) {
						// 问题标题
						let questionNames = {}; // 问题标题: [行数]
						let emptyNameList = []; // 为空的问题标题
						let emptyContentList = []; // 为空的答案内容
						let moreLengthNameList = []; // 超出长度的问题标题
						let moreLengthContentList = []; // 超出长度的答案内容
						let notTextNameList = []; // 非纯文本的问题标题
						let notTextContentList = []; // 非纯文本的答案内容
						let notExistGroupList1 = []; // 一级分类不存在
						let notExistGroupList2 = []; // 二级分类不存在
						let notExistGroupList3 = []; // 三级分类不存在
						let groupHasChildren1 = []; // 一级分类存在子分类
						let groupHasChildren2 = []; // 二级分类存在子分类

						// 遍历表格每行的数据
						firstSheet.forEach((value, index) => {
							// console.log('firstSheet', value, index);

							let category1 = value['一级问题分类'] + '';
							let category2 = value['二级问题分类'] + '';
							let category3 = value['三级问题分类'] + '';
							let name = '';
							let content = '';
							let categoryId = 0;

							if (category1.trim().length > 0) {
								// 校验是否存在
								const group1 = this.existedGroups.find(item => item.name === category1.trim());
								if (group1) {
									categoryId = group1.id;
									if (category2.trim().length > 0) {
										const group2 = group1.children ? group1.children.find(item => item.name === category2.trim()) : null;
										if (group2) {
											categoryId = group2.id;
											if (category3.trim().length > 0) {
												const group3 = group2.children ? group2.children.find(item => item.name === category3.trim()) : null;
												if (group3) {
													categoryId = group3.id;
												} else {
													notExistGroupList3.push(index + 2);
												}
											} else {
												if (group2.children) {
													groupHasChildren2.push(index + 2);
												}
												category3 = '';
											}
										} else {
											notExistGroupList2.push(index + 2);
										}
									} else {
										if (group1.children) {
											groupHasChildren1.push(index + 2);
										}
										category2 = '';
										category3 = '';
									}
								} else {
									// “第x行   一级/二级/三级分类不存在，请重新编辑后再导入”
									console.log('分类不存在', category1, this.existedGroups);
									notExistGroupList1.push(index + 2);
								}
							} else {
								category1 = '';
								category2 = '';
								category3 = '';
							}

							for (let i = 0; i < tempKeys.length; i++) {
								switch (tempKeys[i]) {
									case '问题标题':
										{
											name = value[tempKeys[i]] + '';

											if (name.trim().length > 0) {
												if (name.trim().length > 250) {
													moreLengthNameList.push(index + 2);
												}
												if (typeof name !== 'string') {
													notTextNameList.push(index + 2);
												}
												if (questionNames[name]) {
													questionNames[name].push(index + 2);
												} else {
													questionNames[name] = [index + 2];
												}
											} else {
												emptyNameList.push(index + 2);
											}
										}

										break;
									case '答案内容':
										{
											content = value[tempKeys[i]] + '';
											if (content.trim().length > 0) {
												if (content.trim().length > 2000) {
													moreLengthContentList.push(index + 2);
												}
												if (typeof content !== 'string') {
													notTextContentList.push(index + 2);
												}
											} else {
												emptyContentList.push(index + 2);
											}
										}
										break;
								}
							}
							// "categoryId": 22,"name": "知识库名称111sd111sddsdsd11ssssss1", "answer": "知识库答案", "type": "text", "fileName": null
							this.questionList.push({name, answer: content, type: 'text', fileName: null, categoryId: categoryId});
						});
						// 表格中存在相同的问题标题，弹窗提示“第2,3行   问题标题重复！”
						for (let key in questionNames) {
							if (questionNames[key].length > 1) {
								checkResult += `第 ${questionNames[key].join(',')} 行, 问题标题重复！<br />`;
							}
						}
						// “第x行  问题标题为空，请重新编辑后再导入！”
						if (emptyNameList.length > 0) {
							checkResult += `第 ${emptyNameList.join(',')} 行, 问题标题为空，请重新编辑后再导入！<br />`;
						}
						// “第3,4,5行   答案内容为空，请重新编辑后再导入！”
						if (emptyContentList.length > 0) {
							checkResult += `第 ${emptyContentList.join(',')} 行, 答案内容为空，请重新编辑后再导入！<br />`;
						}
						// “第x，行  格式错误，问题标题最多支持250个字符”
						if (moreLengthNameList.length > 0) {
							checkResult += `第 ${moreLengthNameList.join(',')} 行, 格式错误，问题标题最多支持250个字符<br />`;
						}
						// “第x行  格式错误，答案内容最多支持2000个字符”
						if (moreLengthContentList.length > 0) {
							checkResult += `第 ${moreLengthContentList.join(',')} 行, 格式错误，答案内容最多支持2000个字符”<br />`;
						}
						// “第x行  格式错误，问题标题只能为纯文本
						if (notTextNameList.length > 0) {
							checkResult += `第 ${notTextNameList.join(',')} 行, 格式错误，问题标题只能为纯文本<br />`;
						}
						// “第x行  格式错误，答案内容只能为纯文本
						if (notTextContentList.length > 0) {
							checkResult += `第 ${notTextContentList.join(',')} 行, 格式错误，答案内容只能为纯文本<br />`;
						}
						// “第x行   一级/二级/三级分类不存在，请重新编辑后再导入”
						if (notExistGroupList1.length > 0) {
							checkResult += `第 ${notExistGroupList1.join(',')} 行, 一级分类不存在，请重新编辑后再导入<br />`;
						}
						if (notExistGroupList2.length > 0) {
							checkResult += `第 ${notExistGroupList2.join(',')} 行, 二级分类不存在，请重新编辑后再导入<br />`;
						}
						if (notExistGroupList3.length > 0) {
							checkResult += `第 ${notExistGroupList3.join(',')} 行, 三级分类不存在，请重新编辑后再导入<br />`;
						}
						// 输入的分类名称下存在子分类，弹框提示“第x行，一级/二级下存在子分类，请重新编辑后再导入”
						if (groupHasChildren1.length > 0) {
							checkResult += `第 ${groupHasChildren1.join(',')} 行, 一级分类下存在子分类，请重新编辑后再导入<br />`;
						}
						if (groupHasChildren2.length > 0) {
							checkResult += `第 ${groupHasChildren2.join(',')} 行, 二级分类下存在子分类，请重新编辑后再导入”<br />`;
						}
					} else {
						checkResult = '<b>请勿修改表格表头信息，请重新编辑后再导入！</b><br />' + checkResult;
					}

					// 关闭校验动画
					this.loading = false;
					// 处理校验结果
					if (checkResult.length === 0) {
						if (this.questionList.length === 0) {
							this.reset();
							this.$message.warning('Excel 中没有数据！');
						} else {
							this.uploadFileList = [{ name: file.name, lastModified: file.raw.lastModified, size: file.size }];
							this.$message.success('数据校验成功！');
						}
					} else {
						this.reset();
						this.$alert(`<div style="overflow-y:scroll;overflow-x:hidden;max-height:300px;word-break: break-all;">${checkResult}</div>`, 'Excel 检测失败', {
							confirmButtonText: '确定',
							dangerouslyUseHTMLString: true
						});
					}
				};
			}, 100);
		},
		onUploadProgress(event, file, fileList) {
			fixUploadPercent(this, event, file, fileList);
		}
	}
};
</script>

<style lang="less">
.btns {
	text-align: right;
}

.account {
	.head {
		padding: 20px 0;
	}

	.el-avatar > img {
		width: 100%;
	}
}
</style>

<style lang="less" scoped>
.detail-link {
	/deep/ .el-button {
		width: 80px;
		height: 28px;
		background: #ffffff;
		border: 1px solid #6384fe;
		border-radius: 4px;
		font-size: 12px;
		font-weight: 400;
		color: #6384fe;
		line-height: 28px;
		padding: 0;
	}
}

.download-button {
}

.before-upload-box {
	display: flex;
	flex-direction: column;
	height: 100%;
	justify-content: center;

	.upload-text {
		margin-top: 10px;
	}
}

.upload-box {
	display: flex;
	align-items: center;
	height: 100%;

	.upload-items {
		display: flex;
		flex-direction: row;
		align-items: center;
		padding-left: 10px;
		padding-right: 10px;
		justify-content: center;
		width: 100%;

		.excel-img {
			margin: 0 0 0 0;
		}

		.excel-name {
			margin: 0 0 0 10px;
		}

		.excel-remove {
			padding: 10px 10px 10px 10px;
		}
	}
}
</style>
